home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 16 / IOPROG_16.ISO / soft / macaxsdk / macsdk.hqx / ActiveX DR3 SDK / ActiveX SDK / Container Common / CBaseSite.cpp / CBaseSite.cpp
Encoding:
Text File  |  1997-09-16  |  19.6 KB  |  1,043 lines  |  [TEXT/CWIE]

  1. //
  2. //  CBaseSite.cpp
  3. //
  4. // >>> ⌐ 1996-1997 Microsoft Corporation.  All rights reserved. <<<
  5. //
  6.  
  7. #include "AXContainerHeaders.h"
  8. #include <ctype.h>
  9. #include "MacMisc.h"
  10. #include "CActiveXScheduler.h"
  11. #include "Helpers.h"
  12. #include <CodeFragments.h>
  13. #include "download.h"
  14.  
  15.  
  16. static LPOLESTR StrDup(LPCOLESTR psz);
  17. static     CCodeDownload*    Downloader = NULL;
  18.  
  19. #pragma mark === CBaseSite::Construction & Destruction ===
  20.  
  21. /*************************** Construction/Destruction *****************/
  22.  
  23. //
  24. //  CBaseSite::CreateCBaseSite
  25. //
  26.  
  27. CBaseSite *CBaseSite::CreateSite(void)
  28. {
  29.     return new CBaseSite();
  30. }
  31.  
  32.  
  33. //
  34. //  CBaseSite::CBaseSite
  35. //
  36.  
  37. CBaseSite::CBaseSite(void)
  38. {
  39.     mClientSiteID = 0L;
  40.     m_pszCodeURL = NULL;
  41.     m_BaseURL = NULL;
  42.     m_dwMinimumVersion = 0L;
  43.     m_fHaveInitialStream = false;
  44.     
  45.  
  46.  #ifdef PLUGIN_ADAPTER
  47.     m_pInitialDataStreamNotify = NULL;
  48.     m_pUnattachedList = NULL;
  49. #endif
  50.  
  51.     m_punkObject = NULL;
  52.     m_clsid = CLSID_NULL;
  53.     mUnkOuter = nil;
  54.     mContainerP = nil;
  55.     mContainerData = NULL;
  56.     mObjSiteP = NULL;
  57.     mControlP = NULL;
  58.     mPropertyBagP = NULL;
  59.  
  60.     mCachedDraw = false;
  61.     mCachedContextChange = false;
  62.     mContextIDs = nil;
  63.     mActiveContextID = kAXInvalidContextID;
  64.     mCachedAppState = kAXBeginActivateEventType;
  65.  
  66.     mHavePort = false;
  67.     mOldPortState.ClipRgn = NULL;
  68.     mBindHostP = NULL;
  69.     mNeedLoad = false;
  70.     mDownloadCallbacks.AXGetDownloadPermission = NULL;
  71.     mDownloadCallbacks.AXIsLoaded = NULL;
  72. }
  73.  
  74.  
  75. //
  76. //  CBaseSite::~CBaseSite
  77. //
  78.  
  79. CBaseSite::~CBaseSite(void)
  80. {
  81. #ifdef PLUGIN_ADAPTER
  82.     if (m_pInitialDataStreamNotify != NULL)
  83.         delete m_pInitialDataStreamNotify;
  84. #endif
  85.      if (m_BaseURL != NULL)
  86.         CoTaskMemFree(m_BaseURL);
  87.     if (m_pszCodeURL != NULL)
  88. //        CoTaskMemFree(m_pszCodeURL);
  89.         DisposePtr(m_pszCodeURL);
  90.  
  91.     if ( mContextIDs )
  92.         delete mContextIDs;
  93.         
  94.     if ( mBindHostP )
  95.         delete mBindHostP; 
  96.  
  97.     // Release the container interface
  98.     if ( mContainerP )
  99.         mContainerP->Release();
  100.     
  101.     // Release the unknown outer interface    
  102.     if ( mUnkOuter )
  103.         mUnkOuter->Release();
  104.         
  105. }
  106.  
  107.  
  108. #pragma mark === CBaseSite::Non Interface public functions ===
  109.  
  110. //
  111. //  CBaseSite::SetUnkOuter
  112. //
  113. //    Should be called immediately after creation with an interface
  114. //    that can return an IMacThreadManager interface so 
  115. //    code download can access threading service
  116. //
  117.  
  118. STDMETHODIMP
  119. CBaseSite::SetUnkOuter (IUnknown* inUnkOuter)
  120. {
  121.     UpdateUnkOuter(inUnkOuter);
  122.     return S_OK;    
  123. }
  124.  
  125.  
  126. //
  127. //  CBaseSite::AddParam
  128. //
  129. STDMETHODIMP
  130. CBaseSite::AddParam (Char8* inName, Char8* inValue)
  131. {
  132.     LPOLESTR    LowerCaseName = StrDup(inName);
  133.     HRESULT        hr = S_OK;
  134.     
  135.      if ( LowerCaseName )
  136.         toLower(LowerCaseName);
  137.     else
  138.         return E_OUTOFMEMORY;    
  139.  
  140.     if ( !mPropertyBagP )
  141.     {
  142.            if ((mPropertyBagP = new CPropertyBag()) == NULL)
  143.             return E_OUTOFMEMORY;    
  144.     }
  145.  
  146.     if (strcmp(LowerCaseName, "codebase") == 0)
  147.     {
  148.         if ((m_pszCodeURL = (LPOLESTR)StrDup((Char8*)inValue)) != NULL)
  149.         {
  150.             GetVersionFromURL(m_pszCodeURL, &m_dwMinimumVersion);
  151.         }
  152.     } 
  153.     else if (strcmp(LowerCaseName, "classid") == 0)
  154.     {
  155.         LPOLESTR    LowerCaseValue = StrDup((Char8*) inValue);
  156.         
  157.         if ( LowerCaseValue )
  158.         {
  159.             toLower(LowerCaseValue);
  160.             hr = ConvertCLASSIDtoCLSID(LowerCaseValue, &m_clsid);
  161.             DisposePtr(LowerCaseValue);
  162.         }
  163.     }
  164.     else
  165.     {
  166.         mPropertyBagP->AddParam(LowerCaseName, inValue );
  167.     }
  168.     DisposePtr(LowerCaseName);
  169.  
  170.     return hr;
  171. }
  172.  
  173. //
  174. //  CBaseSite::CreateControl
  175. //
  176.  
  177. STDMETHODIMP
  178. CBaseSite::CreateControl(void)
  179. {
  180.     if(!mBindHostP)
  181.         mBindHostP = new CBindHost(this);
  182.         
  183.     return CreateControlInternal(true);
  184. }
  185.  
  186. STDMETHODIMP
  187. CBaseSite::CreateControlInternal(Boolean Initial)
  188. {
  189.     AXErrorCode         Result = S_OK;
  190.     FILEXTN                fileType = FILEXTN_UNKNOWN;
  191.     Boolean                ConnectionOpen = false;
  192.     CFragConnectionID    FragConnection;
  193.  
  194.     if (m_punkObject != NULL)
  195.         return E_ABORT;
  196.  
  197.     if(Initial)        // only worry about downloading the first time
  198.     {
  199.         //  Attempt to create the object.  The latest OLE Controls guidelines only
  200.         //  require the object to support IUnknown.
  201.         fileType = GetFileTypeFromExtension(m_pszCodeURL);
  202.  
  203.         if(fileType == FILEXTN_INF || fileType == FILEXTN_HQX)
  204.         {
  205.             if((fileType == FILEXTN_INF) || 
  206.                     !CheckCLSIDVersion(m_clsid, m_dwMinimumVersion,
  207.                             &ConnectionOpen, &FragConnection))
  208.             {
  209.                 if (!Downloader && (Downloader = new CCodeDownload()) == NULL)
  210.                     Result = E_FAIL;
  211.                 else
  212.                 {
  213.                     AddRef();    // account for this pointer
  214.                     Result = Downloader->QueueDownload(this);
  215.                 }
  216.             }
  217.         }
  218.     }
  219.     
  220.     if(Result == S_OK)
  221.     {
  222.         Result = CoCreateInstance(m_clsid, NULL, CLSCTX_INPROC_SERVER,
  223.                 IID_IUnknown, (LPVOID *) &m_punkObject);
  224.     }
  225.     
  226.     if(ConnectionOpen)
  227.     {
  228.         CloseConnection (&FragConnection);
  229.         ConnectionOpen = false;
  230.     }
  231.     
  232.     if(mNeedLoad && Result == S_OK)
  233.         Result = LoadControl();
  234.         
  235.     return Result;
  236. }
  237.  
  238. STDMETHODIMP
  239. CBaseSite::LoadControl(void)
  240. {
  241.     LPUNKNOWN     punkPersist;
  242.     HRESULT        Result = S_OK;
  243.  
  244.     mNeedLoad = true;
  245.  
  246.     if(m_punkObject)
  247.     {
  248.         mNeedLoad = false;        // reinitialize this so site can be reused
  249.     
  250.         // See if this is an in-proc object
  251.         if (SUCCEEDED(m_punkObject->QueryInterface(IID_IObjectWithSite, (LPVOID *) &mObjSiteP))) 
  252.         {
  253.             mObjSiteP->SetSite((IUnknown*) (void*)  this);
  254.             if (FAILED(m_punkObject->QueryInterface(IID_IControl, (LPVOID *) &mControlP)))
  255.                 mControlP = nil; 
  256.         } 
  257.         else
  258.             mObjSiteP = NULL;
  259.            
  260.         if ( !mControlP )
  261.             goto CreateFailure;
  262.             
  263.         if (SUCCEEDED(m_punkObject->QueryInterface(IID_IPersistPropertyBag,(LPVOID *) &punkPersist)))
  264.         {
  265.             Result = ((LPPERSISTPROPERTYBAG) punkPersist)->Load( mPropertyBagP, NULL);
  266.             punkPersist->Release();
  267.         
  268.         }
  269.     #ifdef PLUGIN_ADAPTER
  270.         else  if (m_pInitialDataStreamNotify != NULL &&
  271.                     SUCCEEDED(m_punkObject->QueryInterface(IID_IPersistStream,
  272.                     (LPVOID *) &punkPersist)))
  273.         {
  274.             m_pInitialDataStreamNotify->m_SeekPosition = sizeof(CLSID);
  275.             Result = ((LPPERSISTSTREAM) punkPersist)->Load((LPSTREAM)
  276.                 m_pInitialDataStreamNotify);
  277.             punkPersist->Release();
  278.         }
  279.         delete m_pInitialDataStreamNotify;
  280.         m_pInitialDataStreamNotify = NULL;
  281.     #endif
  282.  
  283.         if (FAILED(Result))
  284.             goto CreateFailure;
  285.  
  286.         if (mCachedAppState != kAXBeginActivateEventType)
  287.         {
  288.             EventRecord    TempEvent;
  289.  
  290.             TempEvent.what = osEvt;
  291.             TempEvent.message = suspendResumeMessage << 24;
  292.             if (mCachedAppState == kAXAppActivate)
  293.                 TempEvent.message |= resumeFlag;
  294.             TempEvent.when = ::TickCount();
  295.             TempEvent.where.h = TempEvent.where.v = 0;
  296.             TempEvent.modifiers = 0;
  297.             
  298.             mControlP->DoActivate(mCachedAppState, kAXInvalidContextID, &TempEvent);
  299.         }
  300.  
  301.         if ( mCachedContextChange && mContextIDs && mContextIDs->GetCount() > 0 )
  302.         {
  303.             UInt32            ContextID;
  304.             Int32            Index = 0;
  305.             
  306.             while ( GetContextID(++Index, &ContextID))
  307.             {
  308.                 mControlP->OnContextChange(ContextID, kAXAddContext);
  309.                 if (ContextID == mActiveContextID)
  310.                     mControlP->OnContextChange(ContextID, kAXActivateContext);
  311.             }
  312.             
  313.             mCachedContextChange = false;
  314.  
  315.         }
  316.  
  317.         if ( mCachedDraw && mContextIDs && mContextIDs->GetCount() > 0)
  318.         {
  319.             DrawControl();
  320.             mCachedDraw = false;
  321.         }
  322.  
  323.         if(mDownloadCallbacks.AXIsLoaded)
  324.             mDownloadCallbacks.AXIsLoaded(mClientSiteID);
  325.         return S_OK;
  326.     }
  327.     return MK_S_ASYNCHRONOUS;
  328.     
  329.     //  Cleanup after anything that we've already done and unload the object.
  330. CreateFailure:
  331.     DestroyControl();
  332.     return E_FAIL;
  333.  
  334. }
  335.  
  336.  
  337. //
  338. //  CBaseSite::DestroyControl
  339. //
  340.  
  341. STDMETHODIMP
  342. CBaseSite::DestroyControl(void)
  343. {
  344.     if ( mPropertyBagP )
  345.         ReleaseAndNull(mPropertyBagP);
  346.     
  347.     if(mBindHostP != NULL)
  348.         mBindHostP->AbortBindings();
  349.         
  350.     if (mControlP != NULL) 
  351.         ReleaseAndNull(mControlP);
  352.  
  353.     if (mObjSiteP != NULL) 
  354.     {
  355.         mObjSiteP->SetSite(NULL);
  356.         ReleaseAndNull(mObjSiteP);
  357.     }
  358.  
  359.     SafeReleaseAndNull(m_punkObject);
  360.     CoFreeUnusedLibraries();    // unload the com object if not used
  361.  
  362.     return S_OK;
  363. }
  364.  
  365.  
  366. //
  367. //  CBaseSite::SetContainerData
  368. //
  369. //  Sets the container data for the site
  370. //
  371.  
  372. STDMETHODIMP_(Boolean)
  373. CBaseSite::HasNoStreams(void)
  374. {
  375.     return mBindHostP ? mBindHostP->GetCount == 0 : true;
  376. }
  377.  
  378. //
  379. //  CBaseSite::SetContainerData
  380. //
  381. //  Sets the container data for the site
  382. //
  383.  
  384. STDMETHODIMP
  385. CBaseSite::SetContainerData(IUnknown* inContainerP, void  *inContainerData)
  386. {
  387.     // Release the current container interface if necessary
  388.     if (mContainerP)
  389.     {
  390.         mContainerP->Release();
  391.         mContainerP = nil;
  392.         mContainerData = 0;
  393.     }
  394.     
  395.     // if we got a new interface, query it for the new container interface
  396.     // and set the container data
  397.     if ( inContainerP )
  398.     {
  399.         inContainerP->QueryInterface(IID_IContainer, &mContainerP);
  400.         mContainerData = inContainerData;
  401.     }
  402.     
  403.     
  404.        return S_OK;
  405. }
  406.  
  407.  
  408. //
  409. //  CBaseSite::GetContainerData
  410. //
  411. //  Returns the container
  412. //
  413.  
  414. STDMETHODIMP
  415. CBaseSite::GetContainerData(void** outContainerData)
  416. {
  417.     *outContainerData = mContainerData;
  418.     return S_OK;
  419. }
  420.  
  421. //
  422. //  CBaseSite::SetBaseURL
  423. //
  424. //  Sets the base URL for this site
  425. //
  426.  
  427. STDMETHODIMP
  428. CBaseSite::SetBaseURL(Char8* inURL)
  429. {
  430.     if ( m_BaseURL )
  431.     {
  432.         CoTaskMemFree(m_BaseURL);
  433.         m_BaseURL = nil;
  434.     }
  435.         
  436.     m_BaseURL = OleStrdup(inURL);
  437.    
  438.     return S_OK;
  439. }
  440.  
  441. //
  442. //  CBaseSite::GetDownloadPermission
  443. //
  444. //    all containers MUST OVERRIDE this
  445. // This function can be called multiple times for controls that
  446. // have multiple files to download
  447. Boolean8 CBaseSite::GetDownloadPermission(char*    URLString)
  448. {
  449. #pragma unused (URLString)
  450.     return true;
  451. }
  452.  
  453.  
  454. #pragma mark === CBaseSite::Non Interface protected functions ===
  455.  
  456.  
  457. //
  458. //  CBaseSite::UpdateUnkOuter
  459. //
  460. void CBaseSite::UpdateUnkOuter (IUnknown* inUnkOuter)
  461. {
  462.     // Release the current UnkOuter if we have one
  463.     if ( mUnkOuter )
  464.     {
  465.         mUnkOuter->Release();
  466.         mUnkOuter = nil;
  467.     }
  468.     
  469.     // if we got a new outer unknown, record it and addref it
  470.     if ( inUnkOuter )
  471.     {        
  472.         mUnkOuter = inUnkOuter;
  473.         mUnkOuter->AddRef();
  474.     }
  475. }
  476.  
  477. //
  478. //    CBaseSite::DrawControl
  479. //
  480.  
  481. void CBaseSite::DrawControl(void)
  482. {
  483.     if ( mControlP )
  484.     {
  485.         AXDrawContext    Context = {kAXBeginPortType};
  486.         UInt32            ContextID;
  487.         long            Index = 1;
  488.         
  489.         while( GetContextID(Index++, &ContextID) )
  490.         {
  491.             if(AcquireContext(ContextID, &Context) == S_OK)
  492.             {
  493.                 mControlP->Draw(&Context);
  494.                 ReleaseContext(&Context);
  495.             }
  496.         }
  497.     }
  498.     else
  499.         mCachedDraw = true;
  500. }
  501.  
  502.  
  503. //
  504. //  CBaseSite::SavePortState
  505. //
  506.  
  507. void CBaseSite::SavePortState(AXPlatformPort* Port)
  508. {
  509.     // Save off the current port
  510.     ::GetPort(&mSavePort);
  511.     
  512.     // Set the current port to the one requested
  513.     ::SetPort(Port);
  514.     
  515.     // Save off the port rect and clip
  516.     mOldPortState.PortRect = Port->portRect;
  517.     mOldPortState.ClipRgn = NewRgn();
  518.     ::GetClip(mOldPortState.ClipRgn);
  519.     
  520.     // Save off the pen state
  521.     ::GetPenState(&mOldPortState.PenState);
  522.     mOldPortState.TextFont = Port->txFont;
  523.     mOldPortState.TextMode = Port->txMode;
  524.     mOldPortState.TextSize = Port->txSize;
  525.     mOldPortState.TextFace = Port->txFace;
  526.     ::GetForeColor(&mOldPortState.ForeColor);
  527.     ::GetBackColor(&mOldPortState.BackColor);
  528. }
  529.  
  530.  
  531. //
  532. //  CBaseSite::RestorePortState
  533. //
  534.  
  535. void CBaseSite::RestorePortState(void)
  536. {
  537.     //  Undo everything we did to "thePort" in AcquirePort.
  538.     ::SetOrigin(mOldPortState.PortRect.left, mOldPortState.PortRect.top);
  539.     if (mOldPortState.ClipRgn)
  540.     {
  541.         ::SetClip(mOldPortState.ClipRgn);
  542.         ::DisposeRgn(mOldPortState.ClipRgn);
  543.         mOldPortState.ClipRgn = NULL;
  544.     }
  545.  
  546.     // Restore the current state of things
  547.     ::SetPenState(&mOldPortState.PenState);
  548.     ::TextFont(mOldPortState.TextFont);
  549.     ::TextFace(mOldPortState.TextFace);
  550.     ::TextMode(mOldPortState.TextMode);
  551.     ::TextSize(mOldPortState.TextSize);
  552.     ::RGBForeColor(&mOldPortState.ForeColor);
  553.     ::RGBBackColor(&mOldPortState.BackColor);
  554.  
  555.     // Set back to original port
  556.     ::SetPort(mSavePort);
  557.  
  558. }
  559.  
  560.  
  561. //
  562. //  CBaseSite::GetContextID
  563. //
  564. //    all containers MUST OVERRIDE this
  565.  
  566. Boolean8
  567. CBaseSite::GetContextID(Int32 inContextIndex, UInt32* outContextID)
  568. {
  569. #pragma unused (inContextIndex, outContextID)
  570.     return false;
  571. }
  572.  
  573. #pragma mark === CBaseSite::IUnknown Interfaces ===
  574.  
  575. /************************* IUnknown Interfaces *************************/
  576. //
  577. //  CBaseSite::IUnknown::QueryInterface
  578. //
  579. //  Returns a pointer to the specified interface on a component to which a
  580. //  client currently holds an interface pointer.
  581. //
  582. STDMETHODIMP
  583. CBaseSite::QueryInterface(REFIID inRefID, void** outObj)
  584. {
  585.     AXErrorCode Result = CBaseCOM::QueryInterface( inRefID, outObj);
  586.     
  587.     if ( Result == E_NOINTERFACE )
  588.     {
  589.         void* pv = nil;
  590.  
  591.         if ( inRefID == IID_IControl )
  592.             pv = (void*)(IControl*) this;
  593.         else if ( inRefID == IID_IContainerSite )
  594.             pv = (void*)(IContainerSite*) this;
  595.         else if (inRefID == IID_IServiceProvider)
  596.             pv = (void*)(LPSERVICEPROVIDER) this;
  597.         else if (inRefID == IID_IBindHost)
  598.         {
  599.             if(!mBindHostP)
  600.                 mBindHostP = new CBindHost(this);
  601.             pv = (void*)(LPBINDHOST) mBindHostP;
  602.         }
  603.         else if ( mUnkOuter ) // Check the outer unknown
  604.         {
  605.             Result = mUnkOuter->QueryInterface(inRefID, outObj);
  606.             if ( Result == S_OK )
  607.                 return Result;
  608.         }
  609.             
  610.         *outObj = pv;
  611.     
  612.         if ( pv )
  613.         {
  614.             ((IUnknown*) pv)->AddRef();
  615.             Result = S_OK;
  616.         }
  617.     }
  618.     
  619.     return Result;
  620.  
  621. }
  622.  
  623.  
  624.  
  625. #pragma mark === CBaseSite::IContainerSite Interfaces ===
  626.  
  627. //
  628. //  CBaseSite::IContainerSite::GetContainer
  629. //
  630. //  Returns the container
  631. //
  632.  
  633. STDMETHODIMP
  634. CBaseSite::GetContainer(IContainer** outContainer)
  635. {
  636.     // Caller's responsibility to AddRef the container interface
  637.     *outContainer = mContainerP;
  638.     return S_OK;
  639. }
  640.  
  641.  
  642. //
  643. //  CBaseSite::IContainerSite::RequestFocus
  644. //
  645. //  attempt to manage focus
  646. //
  647.  
  648. STDMETHODIMP
  649. CBaseSite::RequestFocus ( Boolean8 /* inAcquire */, AXFocusSet /* inFocus */)
  650. {
  651.     return E_NOTIMPL;
  652. }
  653.  
  654.  
  655. //
  656. //  CBaseSite::RequestSizeChange
  657. //
  658. //  how to change the controls size
  659. //
  660.  
  661. STDMETHODIMP
  662. CBaseSite::RequestSizeChange ( Point* /* ioSize */)
  663. {
  664.     return E_NOTIMPL;
  665. }
  666.  
  667. //
  668. //  CBaseSite::OnChange
  669. //
  670. //  Notification that something of interest changed in the control
  671. //
  672.  
  673. STDMETHODIMP
  674. CBaseSite::OnChange (AXChangeType inChangeType)
  675. {
  676.     switch (inChangeType)
  677.     {
  678.         case kAXUsedAreaChange:
  679.             {
  680.                 AXDrawContext    Context = {kAXBeginPortType};
  681.                 UInt32            ContextID;
  682.                 long            Index = 1;
  683.                 
  684.                 while( GetContextID(Index++, &ContextID) )
  685.                 {
  686.                     AcquireContext(ContextID, &Context);
  687.                     ::EraseRect(&Context.Location);
  688.                     ReleaseContext(&Context);
  689.                 }
  690.             }
  691.             break;
  692.         case kAXViewChange:
  693.         case kAXDataChange:
  694.         default:
  695.             break;
  696.     }
  697.  
  698.     return S_OK;    // we don't care here
  699. }
  700.  
  701. //
  702. //  CBaseSite::IContainerSite::AcquireContext
  703. //
  704.  
  705. STDMETHODIMP
  706. CBaseSite::AcquireContext(Uint32 /*inContextID*/, AXDrawContext* /*outContext*/)
  707. {    
  708.     return  E_FAIL;
  709. }
  710.  
  711.  
  712. //
  713. //  CBaseSite::IContainerSite::ReleaseContext
  714. //
  715.  
  716. STDMETHODIMP
  717. CBaseSite::ReleaseContext(AXDrawContext* inContext)
  718. {
  719. #pragma unused (inContext)
  720.  
  721.     if (!mHavePort) 
  722.     {
  723.         //  Unbalanced GetDC/ReleaseDC calls.  Return an error.
  724.         return  E_FAIL;
  725.     }
  726.  
  727.     RestorePortState();
  728.  
  729.     mHavePort = FALSE;
  730.  
  731.     return S_OK;
  732. }
  733.  
  734.  
  735. //
  736. //  CBaseSite::IContainerSite::SetIdleTime
  737. //
  738.  
  739. STDMETHODIMP
  740. CBaseSite::SetIdleTime(Int32 inWaitTicks, Uint32 inRefCon)
  741. {
  742.     CActiveXScheduler*    Scheduler = CActiveXScheduler::GetActiveXScheduler(true);
  743.     AXErrorCode            Result = E_FAIL;
  744.  
  745.     if (Scheduler)
  746.     {
  747.         if (inWaitTicks == kAXRemoveAllIdlers)
  748.             Result = Scheduler->RemoveControl(this);
  749.         else if (inWaitTicks == kAXRemoveIdler)
  750.             Result = Scheduler->RemoveControlByRefCon(this, inRefCon);
  751.         else
  752.         {
  753.             Result = Scheduler->ScheduleControl(inWaitTicks == kAXIdleAfterAllEvents, inWaitTicks, this, inRefCon);
  754.         }
  755.     }
  756.  
  757.     return Result;
  758. }
  759.  
  760.  
  761.  
  762. #pragma mark === CBaseSite::IControl Interfaces ===
  763.  
  764. //
  765. //  CBaseSite::IControl::Draw
  766. //
  767. //  Calls the embedded object and tells it to paint itself.
  768. //
  769.  
  770. STDMETHODIMP
  771. CBaseSite::Draw(AXDrawContext* inContext)
  772. {
  773.     if ( mControlP )
  774.         mControlP->Draw(inContext);
  775.     else
  776.         mCachedDraw = true;
  777.     
  778.     return S_OK;
  779. }
  780.  
  781.  
  782. //
  783. //  CBaseSite::IControl::OnContextChange
  784. //
  785. //  Adds a context to the control
  786. //
  787.  
  788. STDMETHODIMP
  789. CBaseSite::OnContextChange(UInt32 inContextID, AXContextCommand inCommand)
  790. {
  791.     // if the context IDs list has not been created, create it
  792.     if ( !mContextIDs )
  793.     {
  794.         mContextIDs = new LArray(sizeof(Uint32));
  795.         if ( !mContextIDs )
  796.             return E_FAIL;
  797.     }
  798.     
  799.     // Update our list of context IDs appropriately
  800.     switch ( inCommand )
  801.     {
  802.         case kAXAddContext:
  803.             mContextIDs->InsertItemsAt(1, 0x7fffffff, &inContextID);
  804.             break;
  805.             
  806.         case kAXRemoveContext:
  807.             mContextIDs->Remove(&inContextID);
  808.             break;
  809.             
  810.         case kAXActivateContext:
  811.             mActiveContextID = inContextID;
  812.             break;
  813.             
  814.         case kAXDeactivateContext:
  815.             mActiveContextID = kAXInvalidContextID;
  816.             break;
  817.             
  818.     }
  819.     
  820.     // if we have a control, let it handle the context change
  821.     // otherwise, we cache the context change    
  822.     if ( mControlP )
  823.     {
  824.         AXErrorCode err =  mControlP->OnContextChange(inContextID, inCommand);
  825.         
  826.         // if we still have a pending cached draw, clear out here
  827.         if ( err == S_OK && mCachedDraw && inCommand == kAXActivateContext )
  828.         {
  829.             DrawControl();
  830.             mCachedDraw = false;
  831.         }
  832.         
  833.         mCachedContextChange = false;  // Once we have a control, no need to have this flag set any more
  834.         
  835.         return err;
  836.  
  837.     }
  838.     else
  839.     {
  840.         if ( inCommand == kAXAddContext || inCommand == kAXActivateContext )
  841.             mCachedContextChange = true;
  842.            return S_OK;
  843.        }
  844. }
  845.  
  846.  
  847. //
  848. //  CBaseSite::IControl::GetID
  849. //
  850. //  Returns the ID of the control
  851. //
  852.  
  853. STDMETHODIMP
  854. CBaseSite::GetID(Int32 inBufferSize, Char8* outID)
  855. {
  856.     if ( mControlP )
  857.         return mControlP->GetID(inBufferSize, outID);
  858.     else
  859.     {
  860.         outID[0] = 0;    // return null string    
  861.         return E_FAIL;
  862.     }
  863. }
  864.  
  865. //
  866. //  CBaseSite::IControl::GetUsedArea
  867. //
  868. //  Returns the used area of the control
  869. //
  870.  
  871. STDMETHODIMP
  872. CBaseSite::GetUsedArea(AXPlatformRegion* outUsedArea)
  873. {
  874.     if ( mControlP )
  875.         return mControlP->GetUsedArea(outUsedArea);
  876.     else
  877.         return E_FAIL;
  878. }
  879.  
  880. //
  881. //  CBaseSite::IControl::SetFocus
  882. //
  883. //  Sets or removes focus from this site
  884. //
  885.  
  886. STDMETHODIMP
  887. CBaseSite::SetFocus(AXFocusCommand inCommand, AXFocusSet inFocus)
  888. {
  889.     AXErrorCode    theResult = S_OK;
  890.  
  891.     if ( mControlP )
  892.         theResult = mControlP->SetFocus(inCommand, inFocus);
  893.     else
  894.         theResult = E_FAIL;
  895.         
  896.     return theResult;
  897. }
  898.  
  899.  
  900. //
  901. //  CBaseSite::IControl::DoMouse
  902. //
  903.  
  904. STDMETHODIMP
  905. CBaseSite::DoMouse(AXMouseEventType inMouseET, AXPlatformEvent* inEvent)
  906. {
  907.     AXErrorCode    theResult = S_OK;
  908.     
  909.     if ( mControlP )
  910.         theResult = mControlP->DoMouse(inMouseET, inEvent);
  911.     
  912.     return theResult;
  913. }
  914.  
  915.  
  916. //
  917. //  CBaseSite::IControl::DoKey
  918. //
  919.  
  920. STDMETHODIMP
  921. CBaseSite::DoKey(AXKeyEventType inKeyET, Char8 inChar, AXPlatformEvent* inEvent)
  922. {
  923.     AXErrorCode    theResult = S_OK;
  924.     
  925.     if ( mControlP )
  926.         theResult = mControlP->DoKey(inKeyET, inChar, inEvent);
  927.     
  928.     return theResult;
  929. }
  930.  
  931.  
  932. //
  933. //  CBaseSite::IControl::DoActivate
  934. //
  935.  
  936. STDMETHODIMP
  937. CBaseSite::DoActivate(AXActivateEventType inActiveET, UInt32 inContextID, AXPlatformEvent* inEvent)
  938. {
  939.     AXErrorCode    theResult = S_OK;
  940.  
  941.     if ( mControlP )
  942.         theResult = mControlP->DoActivate(inActiveET, inContextID, inEvent);
  943.     else
  944.     {
  945.         switch (inActiveET)
  946.         {
  947.             case kAXAppActivate:
  948.             case kAXAppDeactivate:
  949.                 mCachedAppState = inActiveET;
  950.                 break;
  951.             case kAXWindowActivate:
  952.             case kAXWindowDeactivate:
  953.                 break;
  954.             default:
  955.                 break;
  956.         }
  957.     }
  958.  
  959.     return theResult;
  960. }
  961.  
  962.  
  963. //
  964. //  CBaseSite::IControl::DoSystemEvent
  965. //
  966.  
  967. STDMETHODIMP
  968. CBaseSite::DoSystemEvent(AXPlatformEvent* inEvent)
  969. {
  970.     AXErrorCode    theResult = S_OK;
  971.     
  972.     if ( mControlP )
  973.         theResult = mControlP->DoSystemEvent(inEvent);
  974.     
  975.     return theResult;
  976. }
  977.  
  978.  
  979. //
  980. //  CBaseSite::IControl::OnIdle
  981. //
  982. //  pass idle events to the control
  983. //
  984.  
  985. STDMETHODIMP
  986. CBaseSite::DoIdle(Uint32 IdleRefCon)
  987. {
  988.     if ( mControlP )
  989.         return mControlP->DoIdle(IdleRefCon);
  990.     else
  991.         return SetIdleTime(kAXRemoveAllIdlers, NULL);
  992. }
  993.  
  994.  
  995. #pragma mark === CBaseSite::IServiceProvider Interface ===
  996.  
  997. //
  998. //  CBaseSite::IServiceProvider::QueryService
  999. //
  1000.  
  1001. STDMETHODIMP
  1002. CBaseSite::QueryService(REFGUID inRSID, REFIID inRefID, void** outObj)
  1003. {
  1004.     AXErrorCode Result;
  1005.  
  1006.     if (inRSID == SID_BindHost) 
  1007.     {
  1008.         //  According to the "OLE Controls/COM Objects for the Internet" spec,
  1009.         //  it's legal for the site to implement this service directly on the
  1010.         //  site object.
  1011.         Result = QueryInterface(inRefID, outObj);
  1012.     }
  1013.     else 
  1014.     {
  1015.         *outObj = NULL;
  1016.         Result = E_NOINTERFACE;
  1017.     }
  1018.  
  1019.     return Result;
  1020. }
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026. #pragma mark === Static Utility Functions ===
  1027.  
  1028. //
  1029. //  StrDup
  1030. //
  1031.  
  1032. static LPOLESTR StrDup(LPCOLESTR psz)
  1033. {
  1034.     LPOLESTR pszDup;
  1035.  
  1036.     if ((pszDup = (LPOLESTR) NewPtr(strlen((char *) psz) + 1)) != NULL)
  1037.         strcpy((char *) pszDup, (const char *) psz);
  1038.  
  1039.     return pszDup;
  1040. }
  1041.  
  1042.  
  1043.